#!/bin/bash

# Script: CentOS 7.8 System Update and OpenSSH Advanced Update Script (Aliyun Mirror & Source Compile)
# Features:
#   1. Modify YUM sources to Aliyun (direct repo file write)
#   2. Update all system patches
#   3. Automatically update OpenSSL to the latest version (source compile, using Tencent Cloud mirror)
#   4. Automatically update OpenSSH to the latest version (source compile, using Tencent Cloud mirror)
#   5. Change SSH port to a random port (20000-40000), ensure authentication settings, and configure firewall/SELinux
#   6. Display final system, OpenSSL, OpenSSH versions and SSH port
#   7. Self-delete script after successful execution

# --- ANSI Color Codes for Highlighting (Brighter Colors) ---
LIGHT_RED='\033[1;31m'    # Bright Red
LIGHT_GREEN='\033[1;32m'  # Bright Green
LIGHT_YELLOW='\033[1;33m' # Bright Yellow
LIGHT_BLUE='\033[1;34m'   # Bright Blue
NC='\033[0m'              # No Color

# --- Function: Auto-confirm with delay ---
auto_confirm_with_delay() {
    local prompt_message="$1"
    local delay="$2"
    echo ""
    echo -e "${LIGHT_YELLOW}INFO:${NC} $prompt_message"
    echo -e "${LIGHT_YELLOW}INFO:${NC} Automatically continuing in $delay seconds..."
    for ((i=$delay; i>=1; i--)); do
        echo -n "$i "
        sleep 1
    done
    echo "Continuing execution."
    return 0 # Always confirms (yes)
}

# --- Security Warning and User Confirmation (with countdown) ---
echo -e "${LIGHT_RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${NC}"
echo -e "${LIGHT_RED}!! WARNING: CentOS 7 reached End Of Life (EOL) on June 30, 2024.          !!${NC}"
echo -e "${LIGHT_RED}!! Your current OS CentOS 7.8 is no longer officially supported and may   !!${NC}"
echo -e "${LIGHT_RED}!! have severe security risks.                                            !!${NC}"
echo -e "${LIGHT_RED}!! It is HIGHLY RECOMMENDED to migrate to a supported OS like CentOS      !!${NC}"
echo -e "${LIGHT_RED}!! Stream, AlmaLinux, Rocky Linux, etc., AS SOON AS POSSIBLE.             !!${NC}"
echo -e "${LIGHT_RED}!! This script connects to archived mirrors for CentOS 7.                 !!${NC}"
echo -e "${LIGHT_RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${NC}"
# First confirmation uses a 3-second delay
auto_confirm_with_delay "Do you understand the above risks and wish to proceed with this script?" 3

# --- Check for root privileges ---
if [[ $EUID -ne 0 ]]; then
   echo -e "${LIGHT_RED}ERROR:${NC} This script must be run with root privileges."
   exit 1
fi

echo -e "${LIGHT_BLUE}INFO:${NC} Script execution started."
echo -e "${LIGHT_BLUE}INFO:${NC} Current time: $(date)"

# --- Function: Download and validate repo file (not used for YUM sources, but kept for other download needs) ---
download_and_validate_file() {
    local url="$1"
    local dest_file="$2"
    local file_name_desc="$3" # e.g., "Aliyun Base" or "Aliyun EPEL"

    echo -e "${LIGHT_BLUE}INFO:${NC} Downloading ${file_name_desc} file from ${url} ..."

    http_code=$(curl -L -s -f -o "$dest_file" -w "%{http_code}" "$url")
    curl_exit_code=$?

    if [ "$curl_exit_code" -ne 0 ]; then
        echo -e "${LIGHT_RED}ERROR:${NC} curl failed to download ${file_name_desc} file. curl exit code: $curl_exit_code (possibly due to HTTP error like 404)."
        echo -e "${LIGHT_RED}ERROR:${NC} URL: $url"
        rm -f "$dest_file"
        return 1
    fi

    if [ "$http_code" -ne 200 ]; then
        echo -e "${LIGHT_RED}ERROR:${NC} Server returned non-200 HTTP status code while downloading ${file_name_desc} file: $http_code"
        echo -e "${LIGHT_RED}ERROR:${NC} URL: $url"
        rm -f "$dest_file"
        return 1
    fi

    if [ ! -s "$dest_file" ] || [ "$(stat -c%s "$dest_file")" -lt 50 ]; then
        echo -e "${LIGHT_RED}ERROR:${NC} Downloaded ${file_name_desc} file '${dest_file}' is empty or too small."
        echo -e "${LIGHT_RED}ERROR:${NC} File content summary (if available):"
        head -n 3 "$dest_file" 2>/dev/null
        rm -f "$dest_file"
        return 1
    fi

    echo -e "${LIGHT_GREEN}SUCCESS:${NC} ${file_name_desc} file downloaded and preliminary validation successful: ${dest_file}"
    return 0
}


# --- 1. Modify YUM Mirror Source to Aliyun ---
echo ""
echo -e "### ${LIGHT_BLUE}STEP 1: Modifying YUM Mirror Source to Aliyun${NC} ###"

BACKUP_DIR="/etc/yum.repos.d/backup_$(date +%Y%m%d%H%M%S)"
echo -e "${LIGHT_BLUE}INFO:${NC} Backing up CentOS-*repo and epel*.repo files in /etc/yum.repos.d/ to $BACKUP_DIR ..."
mkdir -p "$BACKUP_DIR"
repo_files_found=0
if ls /etc/yum.repos.d/CentOS-*.repo 1> /dev/null 2>&1; then
    mv /etc/yum.repos.d/CentOS-*.repo "$BACKUP_DIR/"
    echo -e "${LIGHT_GREEN}SUCCESS:${NC} CentOS-*repo files backed up."
    repo_files_found=1
fi
if ls /etc/yum.repos.d/epel*.repo 1> /dev/null 2>&1; then
    mv /etc/yum.repos.d/epel*.repo "$BACKUP_DIR/"
    echo -e "${LIGHT_GREEN}SUCCESS:${NC} epel*.repo files backed up."
    repo_files_found=1
fi

if [ "$repo_files_found" -eq 0 ]; then
    echo -e "${LIGHT_YELLOW}WARNING:${NC} No standard CentOS-*repo or epel*.repo files found for backup, they might be modified or already third-party sources."
fi

# Write CentOS-Base.repo file (Aliyun Mirror)
echo -e "${LIGHT_BLUE}INFO:${NC} Creating /etc/yum.repos.d/CentOS-Base.repo file (Aliyun Mirror)..."
cat << EOF > /etc/yum.repos.d/CentOS-Base.repo
[base]
name=CentOS-\$releasever - Base - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/\$releasever/os/\$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=\$releasever&arch=\$basearch&repo=os&infra=\$infra
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[updates]
name=CentOS-\$releasever - Updates - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/\$releasever/updates/\$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=\$releasever&arch=\$basearch&repo=updates&infra=\$infra
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[extras]
name=CentOS-\$releasever - Extras - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/\$releasever/extras/\$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=\$releasever&arch=\$basearch&repo=extras&infra=\$infra
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[centosplus]
name=CentOS-\$releasever - Plus - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/\$releasever/centosplus/\$basearch/
#mirrorlist=http://mirrorlist.centos.org/?release=\$releasever&arch=\$basearch&repo=centosplus&infra=\$infra
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
EOF
echo -e "${LIGHT_GREEN}SUCCESS:${NC} /etc/yum.repos.d/CentOS-Base.repo file created."


# Auto-confirm EPEL source configuration
auto_confirm_with_delay "Do you need to configure the Aliyun EPEL source? (EPEL contains many additional common packages)" 6
# Write epel.repo file (Aliyun Mirror)
echo -e "${LIGHT_BLUE}INFO:${NC} Creating /etc/yum.repos.d/epel.repo file (Aliyun Mirror)..."
cat << EOF > /etc/yum.repos.d/epel.repo
[epel]
name=Extra Packages for Enterprise Linux \$releasever - \$basearch - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/epel/\$releasever/\$basearch/
#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-\$releasever&arch=\$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
EOF
echo -e "${LIGHT_GREEN}SUCCESS:${NC} /etc/yum.repos.d/epel.repo file created."
epel_configured=1 # Assumes user chose yes, so always configured

echo -e "${LIGHT_BLUE}INFO:${NC} Cleaning YUM cache..."
yum clean all
echo -e "${LIGHT_BLUE}INFO:${NC} Generating new YUM cache..."
yum makecache
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} YUM makecache failed. Please check source configuration or network."
    echo -e "${LIGHT_RED}ERROR:${NC} Current /etc/yum.repos.d/ directory content:"
    ls -la /etc/yum.repos.d/
    echo -e "${LIGHT_RED}ERROR:${NC} CentOS-Base.repo content preview:"
    head /etc/yum.repos.d/CentOS-Base.repo 2>/dev/null || echo "Could not read CentOS-Base.repo"
    if [[ "$epel_configured" -eq 1 ]]; then
        echo -e "${LIGHT_RED}ERROR:${NC} epel.repo content preview:"
        head /etc/yum.repos.d/epel.repo 2>/dev/null || echo "Could not read epel.repo"
    fi
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} YUM mirror source successfully changed to Aliyun and cache updated."

# --- 2. Update System Patches to the Latest Version ---
echo ""
echo -e "### ${LIGHT_BLUE}STEP 2: Comprehensively updating system patches (from Aliyun archived mirror)${NC} ###"
echo -e "${LIGHT_BLUE}INFO:${NC} This will update all installed packages to the latest versions available in the archived repository. This process may take some time..."
yum update -y
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_YELLOW}WARNING:${NC} Some errors might have occurred during system update. Please check the YUM output above."
else
    echo -e "${LIGHT_GREEN}SUCCESS:${NC} System patches successfully updated to the latest versions from Aliyun archived repository."
fi

# --- Automatically Get Latest OpenSSL and OpenSSH Versions ---
# These variables will be populated by curling the mirror directories.

# Automatically detect the latest stable OpenSSL 1.1.1 version from Tencent Cloud mirror
echo -e "${LIGHT_BLUE}INFO:${NC} Automatically detecting the latest stable OpenSSL 1.1.1 version from Tencent Cloud mirror..."
OPENSSL_SOURCE_MIRROR="https://mirrors.cloud.tencent.com/openssl/source/"
LATEST_OPENSSL_TARBALL=$(curl -s "$OPENSSL_SOURCE_MIRROR" | grep -oE 'openssl-1\.1\.1[a-z]?\.tar\.gz' | sort -V | tail -n1)

if [ -z "$LATEST_OPENSSL_TARBALL" ]; then
    echo -e "${LIGHT_YELLOW}WARNING:${NC} Failed to automatically detect the latest OpenSSL 1.1.1 version. Falling back to default: 1.1.1w"
    OPENSSL_VERSION="1.1.1w"
else
    OPENSSL_VERSION=$(echo "$LATEST_OPENSSL_TARBALL" | sed -E 's/openssl-(.*)\.tar\.gz/\1/')
    echo -e "${LIGHT_GREEN}SUCCESS:${NC} Detected latest OpenSSL version: $OPENSSL_VERSION"
fi

# Automatically detect the latest stable OpenSSH portable version from Tencent Cloud mirror
echo -e "${LIGHT_BLUE}INFO:${NC} Automatically detecting the latest stable OpenSSH portable version from Tencent Cloud mirror..."
OPENSSH_MIRROR_URL="https://mirrors.cloud.tencent.com/OpenBSD/OpenSSH/portable/"
LATEST_OPENSSH_TARBALL=$(curl -s "$OPENSSH_MIRROR_URL" | grep -oE 'openssh-[0-9]+\.[0-9]+p[0-9]+\.tar\.gz' | sort -V | tail -n1)

if [ -z "$LATEST_OPENSSH_TARBALL" ]; then
    echo -e "${LIGHT_YELLOW}WARNING:${NC} Failed to automatically detect the latest OpenSSH version. Falling back to default: 10.0p1"
    SSH_VERSION="10.0p1" # Fallback updated to a reasonable recent version
else
    SSH_VERSION=$(echo "$LATEST_OPENSSH_TARBALL" | sed -E 's/openssh-(.*)\.tar\.gz/\1/')
    echo -e "${LIGHT_GREEN}SUCCESS:${NC} Detected latest OpenSSH version: $SSH_VERSION"
fi

echo -e "${LIGHT_BLUE}INFO:${NC} Automatically detected OpenSSL version: $OPENSSL_VERSION"
echo -e "${LIGHT_BLUE}INFO:${NC} Automatically detected OpenSSH version: $SSH_VERSION"


# --- 3. Update OpenSSL to Specific Version (Source Compile) ---
echo ""
echo -e "### ${LIGHT_BLUE}STEP 3: Updating OpenSSL (Source Compile)${NC} ###"
echo -e "${LIGHT_RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${NC}"
echo -e "${LIGHT_RED}!! WARNING: Compiling OpenSSL from source carries high risks and may affect !!${NC}"
echo -e "${LIGHT_RED}!! system stability.                                                      !!${NC}"
echo -e "${LIGHT_RED}!! Always back up critical files and proceed with caution!                !!${NC}"
echo -e "${LIGHT_RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${NC}"
echo ""

OPENSSL_TARBALL="openssl-${OPENSSL_VERSION}.tar.gz"
# OpenSSL source download URL (using Tencent Cloud mirror)
OPENSSL_DOWNLOAD_URL="https://mirrors.cloud.tencent.com/openssl/source/${OPENSSL_TARBALL}"
OPENSSL_BUILD_DIR="/usr/local/src/openssl_build"
OPENSSL_INSTALL_DIR="/usr/local/openssl" # OpenSSL installation path to avoid conflict with system default

auto_confirm_with_delay "Do you need to compile and install OpenSSL ${OPENSSL_VERSION}?" 6
# Proceed with compile and install logic as auto_confirm_with_delay always returns 0.
echo -e "${LIGHT_BLUE}INFO:${NC} Installing OpenSSL compilation dependencies (perl, zlib-devel)..."
yum install -y perl zlib-devel
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} Failed to install perl or zlib-devel. Please check YUM output."
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} Dependencies installed."

mkdir -p "$OPENSSL_BUILD_DIR"
cd "$OPENSSL_BUILD_DIR" || { echo -e "${LIGHT_RED}ERROR:${NC} Cannot enter $OPENSSL_BUILD_DIR directory."; exit 1; }

echo -e "${LIGHT_BLUE}INFO:${NC} Downloading OpenSSL source: ${OPENSSL_DOWNLOAD_URL} (using Tencent Cloud mirror)..."
if command -v wget &>/dev/null; then
    wget "$OPENSSL_DOWNLOAD_URL"
elif command -v curl &>/dev/null; then
    curl -L -O "$OPENSSL_DOWNLOAD_URL"
fi

if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} OpenSSL source download failed. Please check version number or network connection."
    rm -rf "$OPENSSL_BUILD_DIR"
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} OpenSSL source downloaded."

echo -e "${LIGHT_BLUE}INFO:${NC} Extracting source package..."
tar -xzf "$OPENSSL_TARBALL"
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} Failed to extract OpenSSL source package."
    rm -rf "$OPENSSL_BUILD_DIR"
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} Source package extracted."

# Dynamically get the extracted directory name for OpenSSL
OPENSSL_SRC_DIR=$(tar -tf "$OPENSSL_TARBALL" | head -1 | cut -f1 -d"/")
if [ -z "$OPENSSL_SRC_DIR" ] || [ ! -d "$OPENSSL_BUILD_DIR/$OPENSSL_SRC_DIR" ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} Could not find the extracted OpenSSL source directory. Expected something like 'openssl-${OPENSSL_VERSION}' but got '$OPENSSL_SRC_DIR'."
    exit 1
fi

cd "$OPENSSL_BUILD_DIR/$OPENSSL_SRC_DIR" || { echo -e "${LIGHT_RED}ERROR:${NC} Cannot enter $OPENSSL_BUILD_DIR/$OPENSSL_SRC_DIR directory."; exit 1; }


echo -e "${LIGHT_BLUE}INFO:${NC} Configuring, compiling, and installing OpenSSL..."
# --prefix specifies installation path, shared compiles shared libraries, zlib enables zlib compression support
./config --prefix="$OPENSSL_INSTALL_DIR" shared zlib
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} OpenSSL configuration failed. Please check output."
    echo -e "${LIGHT_RED}ERROR:${NC} Please manually check $OPENSSL_BUILD_DIR/$OPENSSL_SRC_DIR/config.log for detailed errors."
    exit 1
fi

make
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} OpenSSL compilation failed. Please check output."
    exit 1
fi

make install
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} OpenSSL installation failed. Please check output."
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} OpenSSL compiled and installed to $OPENSSL_INSTALL_DIR."

echo -e "${LIGHT_BLUE}INFO:${NC} Configuring dynamic linker to find the new OpenSSL libraries..."
# Add new OpenSSL library path to system dynamic linker configuration
echo "$OPENSSL_INSTALL_DIR/lib" > /etc/ld.so.conf.d/openssl-local.conf
ldconfig # Refresh dynamic linker cache
echo -e "${LIGHT_GREEN}SUCCESS:${NC} Dynamic linker configured."

# Clean up build files
echo -e "${LIGHT_BLUE}INFO:${NC} Cleaning OpenSSL compilation files..."
rm -rf "$OPENSSL_BUILD_DIR"
echo -e "${LIGHT_GREEN}SUCCESS:${NC} Cleanup complete."
echo -e "${LIGHT_GREEN}SUCCESS:${NC} OpenSSL ${OPENSSL_VERSION} successfully installed and configured."


# --- 4. Update OpenSSH to Latest Version (Source Compile) ---
echo ""
echo -e "### ${LIGHT_BLUE}STEP 4: Updating OpenSSH (Source Compile)${NC} ###"
echo -e "${LIGHT_RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${NC}"
echo -e "${LIGHT_RED}!! WARNING: Compiling OpenSSH from source carries high risks and may cause  !!${NC}"
echo -e "${LIGHT_RED}!! SSH service to fail, leading to loss of remote access.                   !!${NC}"
echo -e "${LIGHT_RED}!! Always back up critical files and proceed with caution!                  !!${NC}"
echo -e "${LIGHT_RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${NC}"
echo ""

current_ssh_version_full=$(ssh -V 2>&1)
echo -e "${LIGHT_BLUE}INFO:${NC} Current OpenSSH version: $current_ssh_version_full"

auto_confirm_with_delay "Do you need to compile and install OpenSSH ${SSH_VERSION}?" 6
# Proceed with compile and install logic as auto_confirm_with_delay always returns 0.
# Check if wget or curl is installed
if ! command -v wget &>/dev/null && ! command -v curl &>/dev/null; then
    echo -e "${LIGHT_RED}ERROR:${NC} Neither wget nor curl command found, cannot download OpenSSH source. Please install one of them manually."
    exit 1
fi

# Install compilation dependencies (gcc, make, zlib-devel, pam-devel, libXt-devel)
echo -e "${LIGHT_BLUE}INFO:${NC} Installing OpenSSH compilation dependencies..."
yum install -y gcc make zlib-devel pam-devel libXt-devel
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} Failed to install OpenSSH compilation dependencies. Please check YUM output."
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} Dependencies installed."

# Create working directory
BUILD_DIR="/usr/local/src/openssh_build"
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR" || { echo -e "${LIGHT_RED}ERROR:${NC} Cannot enter $BUILD_DIR directory."; exit 1; }

# OpenSSH source download URL (using Tencent Cloud mirror)
OPENSSH_TARBALL="openssh-${SSH_VERSION}.tar.gz"
OPENSSH_DOWNLOAD_URL="https://mirrors.cloud.tencent.com/OpenBSD/OpenSSH/portable/${OPENSSH_TARBALL}"

echo -e "${LIGHT_BLUE}INFO:${NC} Downloading OpenSSH source: ${OPENSSH_DOWNLOAD_URL} (using Tencent Cloud mirror)..."
if command -v wget &>/dev/null; then
    wget "$OPENSSH_DOWNLOAD_URL"
elif command -v curl &>/dev/null; then
    curl -L -O "$OPENSSH_DOWNLOAD_URL"
fi

if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} OpenSSH source download failed. Please check version number or network connection."
    rm -rf "$BUILD_DIR"
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} OpenSSH source downloaded."

echo -e "${LIGHT_BLUE}INFO:${NC} Extracting source package..."
tar -xzf "$OPENSSH_TARBALL"
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} Failed to extract OpenSSH source package."
    rm -rf "$BUILD_DIR"
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} Source package extracted."

# Dynamically get the extracted directory name for OpenSSH
OPENSSH_SRC_DIR=$(tar -tf "$OPENSSH_TARBALL" | head -1 | cut -f1 -d"/")
if [ -z "$OPENSSH_SRC_DIR" ] || [ ! -d "$BUILD_DIR/$OPENSSH_SRC_DIR" ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} Could not find the extracted OpenSSH source directory. Expected something like 'openssh-${SSH_VERSION}' but got '$OPENSSH_SRC_DIR'."
    exit 1
fi

cd "$BUILD_DIR/$OPENSSH_SRC_DIR" || { echo -e "${LIGHT_RED}ERROR:${NC} Cannot enter $BUILD_DIR/$OPENSSH_SRC_DIR directory."; exit 1; }

# Back up existing OpenSSH configuration and host keys (backup before port modification to allow rollback in case of compilation failure)
SSH_BACKUP_DIR="/etc/ssh_backup_$(date +%Y%m%d%H%M%S)"
echo -e "${LIGHT_BLUE}INFO:${NC} Backing up existing OpenSSH configuration files and host keys to $SSH_BACKUP_DIR ..."
mkdir -p "$SSH_BACKUP_DIR"
cp -a /etc/ssh/sshd_config "$SSH_BACKUP_DIR/" 2>/dev/null
cp -a /etc/ssh/ssh_config "$SSH_BACKUP_DIR/" 2>/dev/null
cp -a /etc/ssh/ssh_host_* "$SSH_BACKUP_DIR/" 2>/dev/null
echo -e "${LIGHT_GREEN}SUCCESS:${NC} OpenSSH configuration and keys backed up."

# Stop and disable old SSH service
echo -e "${LIGHT_BLUE}INFO:${NC} Stopping and disabling old OpenSSH service..."
systemctl stop sshd
systemctl disable sshd
echo -e "${LIGHT_GREEN}SUCCESS:${NC} Old service stopped and disabled."

# Compile and install
echo -e "${LIGHT_BLUE}INFO:${NC} Configuring, compiling, and installing OpenSSH..."
# Set environment variables to ensure OpenSSH compilation can find the newly installed OpenSSL libraries and header files
export CPPFLAGS="-I$OPENSSL_INSTALL_DIR/include"
export LDFLAGS="-L$OPENSSL_INSTALL_DIR/lib"

./configure \
    --prefix=/usr \
    --sysconfdir=/etc/ssh \
    --with-pam \
    --with-ssl-dir="$OPENSSL_INSTALL_DIR" \
    --with-privsep-path=/var/lib/sshd \
    --with-xauth=/usr/bin/xauth \
    --with-md5-passwords \
    --with-libs=-ldl
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} OpenSSH configuration failed. Please check output."
    echo -e "${LIGHT_RED}ERROR:${NC} Please manually check $BUILD_DIR/$OPENSSH_SRC_DIR/config.log for detailed errors."
    exit 1
fi

make
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} OpenSSH compilation failed. Please check output."
    exit 1
fi

make install
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} OpenSSH installation failed. Please check output."
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} OpenSSH compiled and installed."

# Copy new sshd_config example file and prompt user to merge
# Prioritize using the newly compiled default configuration, then proceed with subsequent port and authentication modifications
if [ -f "$BUILD_DIR/$OPENSSH_SRC_DIR/sshd_config" ]; then
    mv /etc/ssh/sshd_config /etc/ssh/sshd_config.old_$(date +%Y%m%d%H%M%S)_pre_new_install
    cp "$BUILD_DIR/$OPENSSH_SRC_DIR/sshd_config" /etc/ssh/sshd_config
    chmod 600 /etc/ssh/sshd_config
    echo -e "${LIGHT_BLUE}INFO:${NC} New sshd_config example file installed to /etc/ssh/sshd_config."
else
    echo -e "${LIGHT_YELLOW}WARNING:${NC} New compiled sshd_config example file not found. Please manually check if OpenSSH installation is complete."
fi

# Copy new ssh_config example file
if [ -f "$BUILD_DIR/$OPENSSH_SRC_DIR/ssh_config" ]; then
    mv /etc/ssh/ssh_config /etc/ssh/ssh_config.old_$(date +%Y%m%d%H%M%S)_pre_new_install
    cp "$BUILD_DIR/$OPENSSH_SRC_DIR/ssh_config" /etc/ssh/ssh_config
    chmod 644 /etc/ssh/ssh_config
    echo -e "${LIGHT_BLUE}INFO:${NC} New ssh_config example file installed to /etc/ssh/ssh_config."
else
    echo -e "${LIGHT_YELLOW}WARNING:${NC} New compiled ssh_config example file not found. Please manually check if OpenSSH installation is complete."
fi


# Ensure host keys exist, generate if not present
if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
    echo -e "${LIGHT_BLUE}INFO:${NC} Generating SSH host keys..."
    ssh-keygen -A
else
    echo -e "${LIGHT_BLUE}INFO:${NC} SSH host keys already exist, skipping generation."
fi

# Register new sshd service (if needed, usually handled by make install)
if [ -f "$BUILD_DIR/$OPENSSH_SRC_DIR/contrib/sshd.pam" ]; then
    cp "$BUILD_DIR/$OPENSSH_SRC_DIR/contrib/sshd.pam" /etc/pam.d/sshd
    echo -e "${LIGHT_BLUE}INFO:${NC} New PAM configuration copied to /etc/pam.d/sshd."
else
    echo -e "${LIGHT_YELLOW}WARNING:${NC} New PAM configuration file 'sshd.pam' not found. Please ensure /etc/pam.d/sshd is correctly configured."
fi

# Ensure systemd service file exists and is enabled
if [ ! -f /usr/lib/systemd/system/sshd.service ]; then
    echo -e "${LIGHT_YELLOW}WARNING:${NC} systemd sshd.service file not found. Attempting to copy from source directory."
    if [ -f "$BUILD_DIR/$OPENSSH_SRC_DIR/contrib/sshd.service" ]; then
        cp "$BUILD_DIR/$OPENSSH_SRC_DIR/contrib/sshd.service" /usr/lib/systemd/system/sshd.service
        systemctl daemon-reload
        echo -e "${LIGHT_GREEN}SUCCESS:${NC} sshd.service file copied and reloaded."
    else
        echo -e "${LIGHT_RED}ERROR:${NC} Could not find sshd.service file. Please manually create or fix systemd service."
        echo -e "${LIGHT_RED}ERROR:${NC} You may need to manually configure systemd to manage the new sshd service."
        echo -e "${LIGHT_RED}ERROR:${NC} Please refer to OpenSSH official documentation or CentOS 7 systemd configuration guide."
        exit 1
    fi
fi

echo -e "${LIGHT_BLUE}INFO:${NC} Testing new sshd configuration..."
/usr/sbin/sshd -t
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} New sshd configuration test failed! Please check for errors in /etc/ssh/sshd_config file."
    echo -e "${LIGHT_RED}ERROR:${NC} Do NOT attempt to start SSH service before fixing configuration issues, otherwise you might lose connectivity!"
    exit 1
else
    echo -e "${LIGHT_GREEN}SUCCESS:${NC} sshd configuration test successful."
fi

# Note: SSH service is not started immediately here; it will be started after port modification
echo -e "${LIGHT_BLUE}INFO:${NC} OpenSSH compilation and installation complete, service not started yet, will start after port modification."


# --- 5. Modify SSH Port to Random Port (20000-40000) and Configure Firewall/SELinux ---
echo ""
echo -e "### ${LIGHT_BLUE}STEP 5: Modifying SSH Port and Configuring Firewall/SELinux${NC} ###"

NEW_SSH_PORT=$(($RANDOM % 20001 + 20000)) # Generate a random port between 20000 and 40000
echo -e "${LIGHT_BLUE}INFO:${NC} Changing SSH port to a random port: $NEW_SSH_PORT"

# Back up current sshd_config just in case (another backup before modification)
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak_port_auth_$(date +%Y%m%d%H%M%S)

echo -e "${LIGHT_BLUE}INFO:${NC} Modifying /etc/ssh/sshd_config file..."
# 1. Delete all existing Port lines, then add the new random port
sed -i '/^Port /d' /etc/ssh/sshd_config
echo "Port $NEW_SSH_PORT" >> /etc/ssh/sshd_config

# 2. Ensure PermitRootLogin is set to yes (convenient for initial testing, you can modify it later as needed after successful connection)
# Check if PermitRootLogin line exists, replace if it does, otherwise add
if grep -qE "^\s*PermitRootLogin\s" /etc/ssh/sshd_config; then
    sed -i 's/^\s*PermitRootLogin\s.*/PermitRootLogin yes/' /etc/ssh/sshd_config
else
    echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
fi

# 3. Ensure PasswordAuthentication is set to yes (convenient for initial testing, you can modify it later as needed after successful connection)
# Check if PasswordAuthentication line exists, replace if it does, otherwise add
if grep -qE "^\s*PasswordAuthentication\s" /etc/ssh/sshd_config; then
    sed -i 's/^\s*PasswordAuthentication\s.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
else
    echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
fi

echo -e "${LIGHT_GREEN}SUCCESS:${NC} sshd_config file modification complete."

# Configure firewall
echo -e "${LIGHT_BLUE}INFO:${NC} Configuring firewall to allow new SSH port $NEW_SSH_PORT..."
if command -v firewall-cmd &>/dev/null; then
    # Use firewalld
    firewall-cmd --zone=public --permanent --add-port=${NEW_SSH_PORT}/tcp
    firewall-cmd --reload
    if [ $? -eq 0 ]; then
        echo -e "${LIGHT_GREEN}SUCCESS:${NC} Firewalld updated and reloaded."
    else
        echo -e "${LIGHT_YELLOW}WARNING:${NC} Firewalld configuration failed. Please manually check firewall settings."
    fi
elif command -v iptables &>/dev/null; then
    # Use iptables (CentOS 7 defaults to firewalld, iptables is a fallback)
    iptables -I INPUT -p tcp --dport ${NEW_SSH_PORT} -j ACCEPT
    service iptables save
    echo -e "${LIGHT_GREEN}SUCCESS:${NC} Iptables updated."
else
    echo -e "${LIGHT_YELLOW}WARNING:${NC} Neither firewalld nor iptables command found. Please manually configure firewall to allow new port $NEW_SSH_PORT."
fi

# Configure SELinux
echo -e "${LIGHT_BLUE}INFO:${NC} Configuring SELinux to allow new SSH port $NEW_SSH_PORT..."
if command -v semanage &>/dev/null; then
    # Check if port already exists with ssh_port_t type, if so, delete and re-add to avoid error
    if semanage port -l | grep -q "^ssh_port_t.*tcp.*${NEW_SSH_PORT}\b"; then
        echo -e "${LIGHT_YELLOW}WARNING:${NC} SELinux port ${NEW_SSH_PORT} (ssh_port_t) already exists, attempting to delete old rule and re-add."
        semanage port -d -t ssh_port_t -p tcp ${NEW_SSH_PORT}
    fi
    semanage port -a -t ssh_port_t -p tcp ${NEW_SSH_PORT}
    if [ $? -eq 0 ]; then
        echo -e "${LIGHT_GREEN}SUCCESS:${NC} SELinux port context added."
    else
        echo -e "${LIGHT_YELLOW}WARNING:${NC} SELinux port context addition failed. If SELinux is in enforcing mode, manual configuration might be needed."
        echo -e "${LIGHT_YELLOW}WARNING:${NC} Try using 'semanage port -a -t ssh_port_t -p tcp ${NEW_SSH_PORT}' or set SELinux to permissive mode ('setenforce 0')."
    fi
else
    echo -e "${LIGHT_YELLOW}WARNING:${NC} semanage command not found. If SELinux is in enforcing mode, manual configuration or disabling SELinux might be needed."
    echo -e "${LIGHT_YELLOW}WARNING:${NC} If SELinux blocks connections, check 'audit.log' (located at /var/log/audit/)."
fi


# Start and enable new OpenSSH service (after all configurations are complete)
echo -e "${LIGHT_BLUE}INFO:${NC} Testing new sshd configuration..."
/usr/sbin/sshd -t
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} New sshd configuration test failed! Please check for errors in /etc/ssh/sshd_config file."
    echo -e "${LIGHT_RED}ERROR:${NC} Do NOT attempt to start SSH service before fixing configuration issues, otherwise you might lose connectivity!"
    exit 1
else
    echo -e "${LIGHT_GREEN}SUCCESS:${NC} sshd configuration test successful."
fi

echo -e "${LIGHT_BLUE}INFO:${NC} Starting and enabling new OpenSSH service..."
systemctl enable sshd
systemctl start sshd
if [ $? -ne 0 ]; then
    echo -e "${LIGHT_RED}ERROR:${NC} Failed to start new OpenSSH service. Please check logs (journalctl -xe) for details."
    echo -e "${LIGHT_RED}ERROR:${NC} You may need to manually restore the old SSH service or troubleshoot."
    exit 1
fi
echo -e "${LIGHT_GREEN}SUCCESS:${NC} New OpenSSH service started and enabled."


# --- 6. Final Status Report ---
echo ""
echo -e "------------------------------------------------------------------------"
echo -e "${LIGHT_BLUE}INFO:${NC} Script execution complete."
echo -e "${LIGHT_YELLOW}IMPORTANT:${NC} As CentOS 7 is EOL, packages downloaded from Aliyun are also archived packages."
echo -e "${LIGHT_YELLOW}IMPORTANT:${NC} Please plan to migrate to a supported operating system AS SOON AS POSSIBLE!"
echo -e "------------------------------------------------------------------------"
echo ""

echo -e "--- ${LIGHT_BLUE}Final System and Software Version Report${NC} ---"
echo -e "${LIGHT_BLUE}INFO:${NC} System patch update status: Complete (from Aliyun archived mirror)"
# Check OpenSSL version, prioritize compiled path, otherwise system path
echo -e "${LIGHT_BLUE}INFO:${NC} OpenSSL Version: $(/usr/local/openssl/bin/openssl version 2>/dev/null || openssl version 2>/dev/null || echo "Unknown")"
# Check OpenSSH version, ensure only the first line is output
echo -e "${LIGHT_BLUE}INFO:${NC} OpenSSH Version: $(/usr/bin/ssh -V 2>&1 | head -n 1 || echo "Unknown")"

# Try to get current listening port from sshd_config, if not found, try from netstat/ss commands
CURRENT_LISTEN_PORT=$(grep -E '^\s*Port\s' /etc/ssh/sshd_config | awk '{print $2}' | head -n 1)
if [ -z "$CURRENT_LISTEN_PORT" ]; then
    CURRENT_LISTEN_PORT=$(ss -tuln | grep sshd | grep -oP '(?<=:)\d+' | head -n 1)
    if [ -z "$CURRENT_LISTEN_PORT" ]; then
        CURRENT_LISTEN_PORT="Unknown (Please verify with 'ss -tuln | grep sshd')"
    fi
fi
echo -e "${LIGHT_BLUE}INFO:${NC} Current SSH Listening Port: $CURRENT_LISTEN_PORT"
echo -e "------------------------------"

if ! rpm -q yum-utils &>/dev/null; then
    echo -e "${LIGHT_BLUE}INFO:${NC} Installing yum-utils to check for required reboot (if not already installed)..."
    yum install -y yum-utils &>/dev/null
fi

if command -v needs-restarting &>/dev/null && needs-restarting -r; then
    echo -e "${LIGHT_YELLOW}WARNING:${NC} A system reboot is recommended to apply all updates (especially for kernel or core library updates like glibc)."
    auto_confirm_with_delay "Do you want to reboot the system now?" 6
    echo -e "${LIGHT_BLUE}INFO:${NC} Rebooting system..."
    reboot
else
    echo -e "${LIGHT_BLUE}INFO:${NC} According to 'needs-restarting' tool, a reboot might not be required at this time."
    echo -e "${LIGHT_BLUE}INFO:${NC} However, if kernel or critical system libraries were updated, manual reboot is still a good practice."
fi

# --- Self-delete the script ---
SCRIPT_PATH="$0"
if [ -f "$SCRIPT_PATH" ]; then
    echo -e "${LIGHT_YELLOW}INFO:${NC} Deleting self-script: $SCRIPT_PATH"
    rm -- "$SCRIPT_PATH"
    echo -e "${LIGHT_GREEN}SUCCESS:${NC} Script deleted successfully."
else
    echo -e "${LIGHT_RED}ERROR:${NC} Could not find script at $SCRIPT_PATH to delete."
fi

exit 0
